package com.jzo2o.es.config;

import cn.hutool.core.date.DatePattern;
import com.jzo2o.es.core.ElasticSearchTemplate;
import com.jzo2o.es.core.impl.ElasticSearchTemplateImpl;
import com.jzo2o.es.properties.EsProperties;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * Elasticsearch配置类，负责初始化ES客户端及相关组件
 */
@Configuration
@EnableConfigurationProperties(EsProperties.class) // 启用ES配置属性绑定
public class EsConfiguration {
    /**
     * 自定义Jackson ObjectMapper，用于ES的JSON序列化/反序列化
     */
    private static final ObjectMapper MAPPER = new ObjectMapper();

    static {
        // 设置属性命名策略为下划线命名（snake_case）
        MAPPER.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
        // 序列化时忽略null值字段
        MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 注册Java时间模块，自定义LocalDateTime的序列化/反序列化格式
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN);
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFormatter));
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFormatter));
        MAPPER.registerModule(javaTimeModule);

    }

    /**
     * 构建Elasticsearch客户端实例
     * @param esProperties ES配置属性（包含host和port）
     * @return ElasticsearchClient实例
     */
    @Bean
    public ElasticsearchClient esClient(EsProperties esProperties) {
        // 创建REST客户端
        RestClient restClient = RestClient.builder(new HttpHost(esProperties.getHost(), esProperties.getPort())).build();
        // Create the transport with a Jackson mapper
        // 使用自定义ObjectMapper创建JSON映射器
        JacksonJsonpMapper jacksonJsonpMapper = new JacksonJsonpMapper(MAPPER);

        // 创建ES传输层
        ElasticsearchTransport transport = new RestClientTransport(restClient, jacksonJsonpMapper);
        // And create the API client
        // 创建并返回ES客户端
        return new ElasticsearchClient(transport);
    }

    /**
     * 注册Elasticsearch模板实例，作为业务层操作ES的入口
     * @param elasticsearchClient ES客户端实例
     * @return ElasticSearchTemplate实例
     */
    @Bean
    public ElasticSearchTemplate template(ElasticsearchClient elasticsearchClient) {
        return new ElasticSearchTemplateImpl(elasticsearchClient);
    }
}
